/******************************************************************************
 * @File name   :      LinkageSelectTag.java
 *
 * @Author      :      chen shixiang
 *
 * @Date        :      2011-4-19
 *
 * @Copyright Notice: 
 * Copyright (c) 2014 DMS, Inc. All  Rights Reserved.
 * This software is published under the terms of the DMS Software
 * License version 1.0, a copy of which has been included with this
 * distribution in the LICENSE.txt file.
 * 
 * 
 * ----------------------------------------------------------------------------
 * Date                   Who         Version        Comments
 * 2011-4-19 下午05:45:44        chen shixiang     1.0            Initial Version
 *****************************************************************************/
package com.cap.bts.framework.controller.jsptag;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.commons.lang.StringUtils;

/**
 *
 */
public class LinkageSelectTag extends TagSupport {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    private String cssClass = "";
    private Integer level = 3;
    private String headerValues = "";
    private String headerTexts = "";
    private String selectLables = "";
    private String parentCode = "";
    private String onChangeFns = "";
    private String selectIds = "";
    public String getContollerRequestPath() {
        return contollerRequestPath;
    }

    public void setContollerRequestPath(String contollerRequestPath) {
        this.contollerRequestPath = contollerRequestPath;
    }

    private String dataType = "";
    private String selectNames = "";
    private String contollerRequestPath;

    private Boolean create = true;
    
    private String [] _headerValues = null;
    private String [] _headerTexts = null;
    private String [] _selectLables = null;
    private String [] _onChangeFns = null;
    private String [] _selectIds = null;
    private String [] _names = null;

    private final String SPLIT_STR = ",";
    private final String CURR_TIME = "" + System.nanoTime();
    private final String DEFAULT_ID_PRE = "_SELECT_XXXXX_" + CURR_TIME + "_";
    private static final String URI_LINKAGE_SELECT = "/linkageselect/";
    /**
     * {@inheritDoc} 
     * overridden:
     * @Date        :      2011-4-20
     * @see javax.servlet.jsp.tagext.TagSupport#doEndTag()
    **/
    public int doEndTag() throws JspTagException {
	JspWriter out = null;
	try {
	    _init();
	    if (level <= 0 || level > 10) level = 3;
	    out = pageContext.getOut();
	    StringBuffer sb = new StringBuffer();
	    if (create)
	      buildSelect(sb);
	    buildJS(sb);
	    out.write(sb.toString());
	}
	catch (IOException e) {
	    throw new JspTagException("");
	}
	return EVAL_PAGE;
    }
    
    /**
     * @Date        :      2011-4-19
     *
     * @return the cssClass
     */
    public String getCssClass() {
        return cssClass;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param cssClass the cssClass to set
     */
    public void setCssClass(String cssClass) {
        this.cssClass = cssClass;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the level
     */
    public Integer getLevel() {
        return level;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param level the level to set
     */
    public void setLevel(Integer level) {
        this.level = level;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the headerValues
     */
    public String getHeaderValues() {
        return headerValues;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param headerValues the headerValues to set
     */
    public void setHeaderValues(String headerValues) {
        this.headerValues = headerValues;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the headerTexts
     */
    public String getHeaderTexts() {
        return headerTexts;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param headerTexts the headerTexts to set
     */
    public void setHeaderTexts(String headerTexts) {
        this.headerTexts = headerTexts;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the selectLables
     */
    public String getSelectLables() {
        return selectLables;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param selectLables the selectLables to set
     */
    public void setSelectLables(String selectLables) {
        this.selectLables = selectLables;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the parentCode
     */
    public String getParentCode() {
        return parentCode;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param parentCode the parentCode to set
     */
    public void setParentCode(String parentCode) {
        this.parentCode = parentCode;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the onChangeFns
     */
    public String getOnChangeFns() {
        return onChangeFns;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param onChangeFns the onChangeFns to set
     */
    public void setOnChangeFns(String onChangeFns) {
        this.onChangeFns = onChangeFns;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the selectIds
     */
    public String getSelectIds() {
        return selectIds;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param selectIds the selectIds to set
     */
    public void setSelectIds(String selectIds) {
        this.selectIds = selectIds;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the dataType
     */
    public String getDataType() {
        return dataType;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param dataType the dataType to set
     */
    public void setDataType(String dataType) {
        this.dataType = dataType;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @return the selectNames
     */
    public String getSelectNames() {
        return selectNames;
    }
    /**
     * @Date        :      2011-4-19
     *
     * @param selectNames the selectNames to set
     */
    public void setSelectNames(String selectNames) {
        this.selectNames = selectNames;
    }

    /**
     * @Date        :      2011-4-20
     *
     * @return the create
     */
    public Boolean getCreate() {
        return create;
    }

    /**
     * @Date        :      2011-4-20
     *
     * @param create the create to set
     */
    public void setCreate(Boolean create) {
        this.create = create;
    }

    /**
     * @Date        :      2011-4-20
     * @param s
     * @return
     */
    private boolean isNotNullEmpty(String s) {
	return s != null && !"".equals(s.trim());
    }
    
    /**
     * @Date        :      2011-4-20
     */
    private void _init() {
	if (isNotNullEmpty(headerValues)) {
	    _headerValues = headerValues.split(SPLIT_STR);
	}
	if (isNotNullEmpty(headerTexts)) {
	    _headerTexts = headerTexts.split(SPLIT_STR);
	}
	if (isNotNullEmpty(onChangeFns)) {
	    _onChangeFns = onChangeFns.split(SPLIT_STR);
	}
	if (isNotNullEmpty(selectLables)) {
	    _selectLables = selectLables.split(SPLIT_STR);
	}
	if (isNotNullEmpty(selectIds)) {
	    _selectIds = selectIds.split(SPLIT_STR);
	}
	if (isNotNullEmpty(selectNames)) {
	    _names = selectNames.split(SPLIT_STR);
	}
    }
    
    /**
     * @Date        :      2011-4-20
     * @param sb
     * @param s1
     * @param s2
     * @param s3
     * @return
     */
    private StringBuffer jstr(StringBuffer sb, String s1, String s2, String s3) {
	sb.append(s1);
	sb.append(s2);
	sb.append(s3);
	return sb;
    }
    
    /**
     * @Date        :      2011-4-20
     * @param ss
     * @param index
     * @param sb
     * @param s1
     * @param s3
     * @return
     */
    private StringBuffer jstr(String [] ss, int index, StringBuffer sb, String s1, String s3) {
	if (checkLength (ss, index)) {
	    jstr(sb, s1, ss[index], s3);
	}
	return sb;
    }
    
    /**
     * @Date        :      2011-4-20
     * @param o
     * @param index
     * @return
     */
    private boolean checkLength(Object [] o, int index) {
	return (o != null && index < o.length);
    }
    
    /**
     * @Date        :      2011-4-21
     * @param sb
     * @return
     */
    private StringBuffer buildSelect(StringBuffer sb) {
	for(int i = 0; i < level; i++) {
	    if (checkLength(_selectLables, i)) {
		 sb.append(_selectLables[i]);
	    }
	    sb.append("<select ");
	    jstr(_selectIds, i, sb, "id='", "' ");
	    if (!checkLength(_selectIds, i)) {
		 jstr(sb, "id='", DEFAULT_ID_PRE + i, "' ");
	    }
		
	    jstr(_names, i, sb, "name='", "' ");
            if(isNotNullEmpty(cssClass))
	        jstr(sb, "class='", cssClass, "' ");
            else 
        	jstr(sb, "style='", "width:80px", "' ");
		
	    sb.append("></select>");
	}
	return sb;
    }
    
    /**
     * @Date        :      2011-4-20
     * @param sb
     * @return
     */
    private StringBuffer buildJS(StringBuffer sb) {
        if(StringUtils.isBlank(contollerRequestPath)){
            contollerRequestPath = ((HttpServletRequest)pageContext.getRequest()).getContextPath() + URI_LINKAGE_SELECT;
        }
	sb.append("<script>" + 
	"   function setSelectData" + CURR_TIME + "(id, nextid, _head) {" +    
	"      if (_head.length > 0){ $('#' + id).data('_head', _head); }" +    
	"      if (nextid.length > 0) {" +    
	"         $('#' + id).data('_nextid', nextid);" +    
	"      }" +    
	"   }" +    
	"   function changeCall" + CURR_TIME + "() {" +    
	"      var obj = $(this);" +    
	"      var nextid = obj.data('_nextid');" +    
	"      var v = obj.val();var _head;" +    
	"      if(obj.data('_head')){_head = eval('(' + obj.data('_head')+'' + ')');}" +    
	"      var hv = ''; var ht = ''; if (_head) {hv = _head.key;" +    
	"      ht = _head.value; }" +    
	"      if (v != hv) {" +    
	"         dataRequestHandle" + CURR_TIME + "(hv, ht, v, nextid);" +    
	"      }else {emptySelect" + CURR_TIME + "(hv, ht, nextid);}" +    
	"    }" +    
	"    function dataRequestHandle" + CURR_TIME + "(hv, ht, parentCode, nextid) {" +    
	"      $.ajax({" +    
	"         type: 'GET'" +    
	"         ,url: '"+contollerRequestPath+"'" +    
	"               + parentCode" +    
	"         ,async: false" +    
	"         ,dataType: 'json'" +    
	"         ,success: function(data){" +    
	"            if(data) {" +    
	"              var next = $('#' + nextid);" +    
	"              emptySelect" + CURR_TIME + "(hv, ht, nextid);" +    
	"               for(var i = 0; i < data.length; i++) {" +    
	"                 $('<option value=\"' + data[i].id + '\">' + data[i].value + " +    
	"                     '</option>').appendTo(next);" +    
	"               }" +
	"               var v = next.val();hv = '';" +
	"               var _head = eval('(' + $('#' + nextid).data('_head')+'' + ')');" +
	"               if(_head){hv = _head.key;}" +
	"               if(v != hv && next.data('_nextid')){dataRequestHandle" + 
	                       CURR_TIME + "(hv, ht, v, next.data('_nextid')+'');}" +    
	"             }else {" +    
	"                 emptySelect" + CURR_TIME + "(hv, ht, nextid);" +    
	"             }" +    
	"           }" +    
	"         });}" +    
	"      function emptySelect" + CURR_TIME + "(hv, ht, nextid) {" +
	"         hv = '';ht = '';"+
	"         if(nextid) {" +
	"            var _head = eval('(' + $('#' + nextid).data('_head')+'' + ')');" +
	"            if(_head){hv = _head.key;ht = _head.value;}" +
	"            $('#' + nextid).empty();" +
	"            if (hv.length > 0 && ht.length > 0) {" +
	"              $('<option value=\"' + hv + '\">' + ht + '</option>').appendTo($('#' + nextid));" +
	"            }" +
	"           emptySelect" + CURR_TIME + "(hv, ht, $('#' + nextid).data('_nextid'));" +
	"         }" +
	"       }" +
	" ");
	sb.append("$(document).ready(function(){");
	buildCallJS(sb);
	sb.append("});");
	sb.append("</script>");
	return sb;
    }
    
    /**
     * @Date        :      2011-4-21
     * @param sb
     * @return
     */
    private StringBuffer buildCallJS(StringBuffer sb) {
	for(int i = 0; i < level; i++) {
	    if (checkLength(_headerValues, i) &&
		    checkLength(_headerTexts, i)) {
		if (checkLength(_selectIds, i + 1) && (i + 1) < level) {
		    sb.append("setSelectData" + CURR_TIME + "('" + _selectIds[i] + "','" +
			    _selectIds[i+1] + "','{\"key\":\"" + _headerValues[i] +
			    "\",\"value\":\"" + _headerTexts[i] + "\"}');");
		}
		else {
		    if (checkLength(_selectIds, i)) {
			if (i == level - 1)
			    sb.append("setSelectData" + CURR_TIME + "('" + _selectIds[i] + "','" +
				"" + "','{\"key\":\"" + _headerValues[i] + 
				"\",\"value\":\"" + _headerTexts[i] + "\"}');");
			else 
			    sb.append("setSelectData" + CURR_TIME + "('" + _selectIds[i] + "','" +
				    DEFAULT_ID_PRE + (i + 1) + "','{\"key\":\"" + _headerValues[i] + 
					"\",\"value\":\"" + _headerTexts[i] + "\"}');");
		    }else {
			if (i < level -1) {
			    sb.append("setSelectData" + CURR_TIME + "('" + DEFAULT_ID_PRE + i + "','" + 
				    DEFAULT_ID_PRE + (i + 1) + "','{\"key\":\"" + _headerValues[i] +
				    "\",\"value\":\"" + _headerTexts[i] + "\"}');");
			}else {
			    sb.append("setSelectData" + CURR_TIME + "('" + DEFAULT_ID_PRE + i + "','" + 
				    "" + "','{\"key\":\"" + _headerValues[i] +
				    "\",\"value\":\"" + _headerTexts[i] + "\"}');");
			}
		    }
		}
	    }else {
		if (checkLength(_selectIds, i + 1) && (i + 1) < level) {
		    sb.append("setSelectData" + CURR_TIME + "('" + _selectIds[i] + "','" +
			    _selectIds[i+1] + "','');");
		}
		else {
		    if (checkLength(_selectIds, i)) {
			sb.append("setSelectData" + CURR_TIME + "('" + _selectIds[i] + "',''," +
					"'');");
		    }else {
			if (i < (level - 1)) {
			    sb.append("setSelectData" + CURR_TIME + "('" + DEFAULT_ID_PRE + i + "','" +
				    DEFAULT_ID_PRE + (i + 1) + "','');");
			}else {
			    sb.append("setSelectData" + CURR_TIME + "('" + DEFAULT_ID_PRE + i + "',''," +
			    		"'');");
			}
		    }
		}
	    }
	    if (i < (level - 1)) {
		if (checkLength(_selectIds, i)) {
		    if (checkLength(_onChangeFns, i)) {
			sb.append("$('#" + _selectIds[i] + "').change(" + _onChangeFns[i] + ");");
		    }else {
			sb.append("$('#" + _selectIds[i] + "').change(changeCall" + CURR_TIME + ");");
		    }
		}else {
		    if (checkLength(_onChangeFns, i)) {
			sb.append("$('#" + DEFAULT_ID_PRE + i + "').change(" + _onChangeFns[i] + ");");
		    }else {
			sb.append("$('#" + DEFAULT_ID_PRE + i + "').change(changeCall" + CURR_TIME + ");");
		    }
		}
	    }
	}
	
	int i = 0;
	if (!checkLength(_onChangeFns, i)) {
	    if (checkLength(_headerValues, i) && checkLength(_headerTexts, i)) {
		if (checkLength(_selectIds, i + 1) && (i + 1) < level) {
		    sb.append("dataRequestHandle" + CURR_TIME + "('"
			    + _headerValues[i] + "','" + _headerTexts[i]
			    + "','" + parentCode + "','" + _selectIds[i]
			    + "');");
		} else {
		    sb.append("datarequestHandle" + CURR_TIME + "('"
			    + _headerValues[i] + "','" + _headerTexts[i]
			    + "','" + parentCode + "','" + DEFAULT_ID_PRE + i
			    + "');");
		}
	    } else {
		if (checkLength(_selectIds, i + 1) && (i + 1) < level) {
		    sb.append("dataRequestHandle" + CURR_TIME + "('','','"
			    + parentCode + "','" + _selectIds[i] + "');");
		} else {
		    sb.append("dataRequestHandle" + CURR_TIME + "('','','"
			    + parentCode + "','" + DEFAULT_ID_PRE + i + "');");
		}
	    }
	}else{
	    sb.append(_onChangeFns[i] + "();");
	}
	return sb;
    }

}
